﻿/***********************************************************
 *
 *
 * jTmpl v0.1.1 - small template processor for JavaScript.
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * Copyright (c) 2007 Lashko Vlidimir (http://alv.ru)
 *
 * $Id: jtmpl.js 20 2008-01-10 09:01:48Z ostrovok $
 *
************************************************************/

(function(){
var jtmpl = window.jtmpl = function() {

	this.reload();

	this.filter_list = {
		html: function( value, obj ){ return String(value).replace(/\&/gm, '&amp;').replace(/\"/gm, '&quot;').replace(/\</gm, '&lt;').replace(/\>/gm, '&gt;')},
		lc: function( value, obj ){ return String(value).toLowerCase(); },
		uc: function( value, obj ){ return String(value).toUpperCase(); },
		zero2: function( value, obj ){ if ( Number(value) > 9 ) return Number(value); return '0'+ value; }
	};

	this.re_end = /\r*\n+/gm;
	this.re_end = /\r*\n+/gm;
	this.re_quot = /\"/gm;
	this.re_quot_out = /\\\"/gm;
	this.re_squot = /\'/gm;
	this.re_space = /\s+/;
	this.re_s_space = /^\s+/gm;
	this.re_e_space = /\s+$/gm;
	this.re_filters_split = /\||\s+FILTER\s+/;
	this.re_filters_search = /\s*(\||FILTER)\s*/;

	this.re_VARIALS_SHOT = /([^a-zA-Z0-9\._!]+)|([a-zA-Z0-9\._!]+)/igm;

	this.re_VAR_SHOT = /[a-zA-Z0-9\._!]/;
	this.re_number = /^(\-?[0-9]+)|(\-?[0-9]*\.[0-9]+)$/;
	this.re_IN = / IN /i;
	this.re_OPERATOR_MATCH = /\s*([^ ]+)\s+(.*)/i;
	this.re_CONDITION_MATCH = /([^a-zA-Z0-9\._\"\'\!]+)|([a-zA-Z0-9\._\"\'\!]+)/igm;
	this.re_CONDITION_SEARCH = /[^a-zA-Z0-9\._\"\']/;

	this.debug_el = null;
	this.LAid = 0;

	this.tag_s = '<%';
	this.tag_e = '%>';

//	this.GET_CONTENT = jtmpl.GET_CONTENT_TO_LINE;
	this.GET_CONTENT = function (u) { return this.GET_CONTENT_TO_LINE(u); };

	return this;
};

/* Change start and finish tags into template */
jtmpl.prototype.set_tags = function( tag_s, tag_e ) {
	if ( tag_s ) this.tag_s = tag_s;
	if ( tag_e ) this.tag_e = tag_e;
};

jtmpl.prototype.reload = function( id ) {
	if ( !id || id == undefined  ) {
		this.elems = {};
		this.elems_html = {};
	} else {
		this.elems[id] = null;
		this.elems_html[id] = null;
	}
};

jtmpl.prototype.register_compile = function( id, code ) {
		this.elems[id] = code;
		this.elems_html[id] = '';
};

jtmpl.prototype.setEvents = function( type, fun ) {
// Attach a bunch of functions for handling common AJAX events
//jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){

	this.events[type] = fun;
};

jtmpl.prototype.set_debug = function( id ) { this.debug_el = this._get_element(id); };
jtmpl.prototype.do_debug_alert = function( t ) { if ( this.debug_alert ) alert(t); };
jtmpl.prototype.set_debug_alert = function( t ) { this.debug_alert = t; };
jtmpl.prototype.view_debug_alert = function( list ) {
	var line = '';
	for ( var i = 0; i < list.length; i++ ) {
		line += i +'==> ';
		for (var t in list[i]) line += t +': '+ list[i][t];
		line += "\n";
	}
	alert(line);
};

/* You can make new filter function */
jtmpl.prototype.fiter_add = function( title, code ) {
	title = this._trim( title );
	if ( title && code && typeof(code) === 'function' )
		this.filter_list[title] = code;
	else 
		this.do_debug_alert( 'Error add new FILTER '+ title );
};


jtmpl.prototype.process = function( id, id_to, data ) {
	if ( !id_to || id_to == null  ) {
		this.do_debug_alert('process error. No contaner id');
		return false;
	}

	try	{
		this._get_element(id_to).innerHTML = this.print( id, data);
	}
	catch (e) {
		this.do_debug_alert('process error. '+ e);
		return false;
	}

	return true;
};

jtmpl.prototype.print = function( id, data ) {

	if ( !id || id == null ) {
		this.do_debug_alert('process error. No template ID');
		return null;
	}

	if ( typeof data != 'object' ) {
		this.do_debug_alert('process error. input data is not "object"');
		return null;
	}

	this.compile(id);
	var t = this.elems[id];
	var s = this;
	try	{
		return t( s, data );
	}
	catch (e) {
		this.do_debug_alert('process error. '+ e);
	}

	return null;
};

jtmpl.prototype.compile = function( id ) {

	if ( !this.elems[id] ) {
		this.compile_line( id, this.comment_cleaner_by_id( id ) );
	}

	return this.elems[id];
};

jtmpl.prototype.compile_line = function( id, tmpl_line ) {
	var L = null;
	var list = [];
	var exe_fun = "(function(obj,data){return ''})";

	if ( !id || id == undefined || id == '' ) 
		id = new Date().getTime() +'_'+ String(Math.random()).substring(0, 10);

	this.elems_html[id] = tmpl_line;

	if ( tmpl_line ) {
		tmpl_line = String(tmpl_line).replace( this.re_end, ' ' ).replace( this.re_squot, "\'" );
		list = this.get_list_operator( tmpl_line );
		if ( list && list.length > 0 )
			exe_fun = this._exe_list_to_fun_simple( list, true ).replace(/L\+/, 'L');
	}
	if ( this.debug_el &&  this.debug_el != null ) {
		this.debug_el.innerHTML = '';
		this.debug_el.appendChild( document.createTextNode( exe_fun ) );
	}

	try { eval(exe_fun); } catch(e) { this.do_debug_alert('compile_line: '+ e ); }

	this.elems[id] = L;
	return id;
};

jtmpl.prototype.filter = function( fil, invar ) {
	try { return this.filter_list[fil](invar, this); }
	catch (e) { this.do_debug_alert(e); }
	return null;
};

/**********************************************************
***********************************************************
 *
 *
 *
 * Main Function
 *
 *
 *
 *
***********************************************************
**********************************************************/

/* Convert text to ARRAY */
jtmpl.prototype.get_list_operator = function ( tmpl_line ) {

	var i = 0;
	var main = [];
	var level = 0;

	var sL = tmpl_line.length;

	var prev = 0;

	var p1 = tmpl_line.indexOf(this.tag_s, 0);
	var p2 = tmpl_line.indexOf(this.tag_e, p1);

	if( p1 == -1 || p2 == -1 )
		return [ { 'TEXT': tmpl_line.replace( this.re_quot, '\\"' ), 'TYPE': 'LINE', 'LEVEL': -1 } ];

	while ( p1 > -1 && p2 > -1 ) {
		if( prev < p1 ) {
			main[i] = { 'TYPE': 'LINE', 'EXE': 'LINE', 'TEXT': tmpl_line.substring( prev, p1 ).replace( this.re_quot, '\\"' ), 'LEVEL': -1 };
			i++;
		}

		var operator = tmpl_line.substring( (p1 + 2), p2 );
		var res = operator.match( this.re_OPERATOR_MATCH );
		if ( !res || typeof res != 'object' || !(res instanceof Array) || res.length == 0 ) { res = ['']; }
		else { for (var t in res ){ res[t] = this._trim(res[t]) } }

		main[i] = { 'TEXT': operator, 'TYPE': 'OPERATOR', 'START': (p1 + 2), 'FINISH': p2, 'LEVEL': level };
		switch (res[1]) {
			case 'END':
					level--;
					main[i].LEVEL--;
					main[i].EXE = 'END';
				break;
			case 'SET':
			case 'CALL':
			case 'INSERT':
			case 'ELSIF':
			case 'ELSE':
			case 'INCLUDE':
			case 'DEFAULT':
			case 'PROCESS':
			case 'IFNEXT':
			case 'IFCONTINUE':
			case 'IFLAST':
			case 'IFBREAK':
					main[i].EXE = res[1];
					main[i].TEXT = res[2];
				break;
			case 'NEXT':
			case 'CONTINUE':
			case 'LAST':
			case 'BREAK':
					main[i].EXE = res[1];
					main[i].TEXT = '';
				break;
			case 'FOR':
			case 'IF':
			case 'UNLESS':
					level++;
					main[i].EXE = res[1];
					main[i].TEXT = res[2];
				break;
			case 'GET':
					main[i].EXE = 'VAR';
					main[i].TEXT = res[2];
				break;
			default: /* as GET */
					main[i].EXE = 'VAR';
					main[i].TEXT = this._trim( operator );
				break;
		}

		i++;
		if ( p2 < ( sL - 2 ))
			main[i] = { 'EXE': 'LINE', 'TYPE': 'LINE', 'TEXT': tmpl_line.substring( p2 + 2 ).replace( this.re_quot, '\\"' ), 'LEVEL': -1  };

		prev = p2 + 2;
		p1 = tmpl_line.indexOf(this.tag_s, prev);
		p2 = tmpl_line.indexOf(this.tag_e, p1);
	}

	return main;
};

jtmpl.prototype._exe_list_to_fun_simple = function( list, is_function ) {

	var start_is_function = is_function;
	if (!is_function) is_function = false;
	var ifLevel = list[0].LEVEL + 1;

	if (!is_function) {
		for ( var k = 0; k < list.length; k++ ) {
			if ( ifLevel == list[k].LEVEL && ( 'FOR' == list[k].EXE || 'FOREACH' == list[k].EXE ))  {
				is_function = true;
				break;
			}
		}
	}

	var fun = "";
	if ( is_function ) fun += " L+=(function( obj, data, loop){ var to=null, from=null, L='';";

	for ( var i = 0; i < list.length; i++ ) {
		var se = list[i];

		if ( -1 == se.LEVEL ) {
			fun += ' L+="'+  se.TEXT +'";';
			continue;
		}

		if ( 'OPERATOR' != se.TYPE ) continue;

		var out = { j: i };
		var getfats = null;
		switch ( se.EXE ) {
			case 'END': break;
			case 'CALL':
/*					fun += " "+ this._variable_parse(se.TEXT, "''" ) +";"; */
				break;
			case 'VAR':
					fun += " L+="+ this._variable_parse(se.TEXT, "''" ) +";";
				break;
			case 'PROCESS':
			case 'INCLUDE':
					fun += this._operator_include( se, list, out );
				break;
			case 'INSERT':
					fun += this._operator_insert( se, list, out );
				break;
			case 'DEFAULT':
					this.do_debug_alert('No case DEFAULT.TODO');
				break;
			case 'SET':
					fun += this._operator_set( se, list, out );
				break;
			case 'FOR':
					fun += this._operator_for( se, list, out );
				break;
			case 'NEXT':
			case 'CONTINUE':
					fun += " continue; ";
				break;
			case 'LAST':
			case 'BREAK':
					fun += " break; ";
				break;
			case 'UNLESS':
			case 'IF':
					fun += this._operator_if( se, list, out );
				break;
		}
		i = out.j;
	}

	if (is_function) {
		fun +=" return L;})";
		if (!start_is_function) fun += "( obj, data, loop )";
	}
	return fun;
};

/* Sigle operator actions...  */
jtmpl.prototype._operator_insert = function( se, list, iOb ) {
	var fun = '';

	if ( se.TEXT.indexOf('"') == 0 && se.TEXT.lastIndexOf('"') == (se.TEXT.length - 1) )
		se.TEXT = "'"+ se.TEXT.substring( 1, ( se.TEXT.length - 1 ) ) +"'";

	var id = this._variable_parse(se.TEXT, "''" );
	if ( id == se.TEXT && String(id).substr(0, 1) != '@') {
		/* Static */
		var line = this.comment_cleaner_by_id( id );
		if ( line ) {
			line = String(line).replace( this.re_end, ' ' ).replace( this.re_squot, "\'" );
			fun += " L+='"+ line +"';";
		}
	} else {
		/* Dinamic */
		fun += "L+=obj.comment_cleaner_by_id('"+ id +"');";
	}

	return fun;
};

jtmpl.prototype._operator_include = function( se, list, iOb ) {
	var fun = '';

	if ( 'OPERATOR' == se.TYPE && 'INCLUDE' == se.EXE ) {	fun += "to=obj._clone(data);"; }
	else  {	fun += "to=data;"; }

	var id = this._variable_parse(se.TEXT, "''" );

	if ( se.TEXT == id && String(id).substr(0, 1) != '@' ) {
		id = this._chop( se.TEXT, ["'", '"'] );
		this.compile( id );
		fun += "L+=obj.elems['"+ id +"'](obj,to);";
	} else {
		fun += "from=String("+ id +");";
		fun += "L+=obj.print(from,to);";
	}
	fun += "to=null;from=null;";

	return fun;
};

jtmpl.prototype._operator_set = function( se, list, iOb ) {
	var fun = '';
	var p1 = se.TEXT.indexOf('=');
	if ( p1 < -1 ) return '';

	var variable	= this._trim( se.TEXT.substring( 0, p1) );
	var value		= this._trim( se.TEXT.substring( p1 + 1 ) );
	fun += " to="+ this._variable_parse( value, 'null' ) + ";"+ this._create_variable( variable ) +";to=null;";
	return fun;
};

jtmpl.prototype._operator_for = function( se, list, iOb ) {
	var fun = '';
	var level = se.LEVEL + 1;
	this.LAid++;
	var nowLAid = this.LAid;

	var subList = new Array();
	while ( level != se.LEVEL && iOb.j < ( list.length - 1 ) ) {
		iOb.j++;
		level = list[iOb.j].LEVEL;
		subList.push(list[iOb.j]);
	}

	if ( level != se.LEVEL ) return '';
	if ( !subList || subList.length == 0 ) return '';

	var subListLIST = new Array();
	var subListCondition = new Array();
	var ifLevel = se.LEVEL + 1;
	var sw = 0;

	subListLIST[0] = new Array();
	subListCondition[0] = se;

	for ( var k = 0; k < ( subList.length - 1 ); k++ ) {
		if ( ifLevel == subList[k].LEVEL && ( 'IFCONTINUE' == subList[k].EXE || 'IFNEXT' == subList[k].EXE || 'IFLAST' == subList[k].EXE || 'IFBREAK' == subList[k].EXE )) {
			sw++;
			subListLIST[sw] = new Array();
			subListCondition[sw] = subList[k];
			continue;
		}
		subListLIST[sw].push(subList[k]);
	}


	if ( !subListCondition || subListCondition.length == 0 ) return '';
	if ( subListCondition.length == 1 && subListCondition[0].length == 0 ) return '';

	var param = se.TEXT.split(this.re_IN);
	param[0] = this._trim( param[0] );
	fun += "var LA"+nowLAid+"="+ this._variable_parse( this._trim( param[1] ), 'null' ) +";";
	fun += "if(obj._check_loop(LA"+nowLAid+"))for(var i"+nowLAid+"=0;i"+nowLAid+"<LA"+nowLAid+".length;i"+nowLAid+"++){";
	fun += "var loop=obj._get_loop_data_shot( data, '"+ param[0] +"', LA"+nowLAid+", i"+nowLAid+" );";
	
	/* Go all subListIF */
	for ( var k = 0; k < subListCondition.length; k++ ) {
		if ( 'IFCONTINUE' == subListCondition[k].EXE || 'IFNEXT' == subListCondition[k].EXE )
			fun += ' if('+ this._get_condition_line( subListCondition[k].TEXT, subListCondition[k].EXE ) +') continue;';
		else if ( 'IFBREAK' == subListCondition[k].EXE || 'IFLAST' == subListCondition[k].EXE )
			fun += ' if('+ this._get_condition_line( subListCondition[k].TEXT, subListCondition[k].EXE ) +') break;';

		if ( 0 == subListLIST[k].length ) continue;
		fun += this._exe_list_to_fun_simple( subListLIST[k], false );
	}

	fun += "}LA"+nowLAid+"=null;";
	return fun;
};

jtmpl.prototype._operator_if = function( se, list, iOb ) {
	var fun = '';
	var level = se.LEVEL + 1;

	var subList = new Array();
	while ( level != se.LEVEL && iOb.j < ( list.length - 1 ) ) {
		iOb.j++;
		level = list[iOb.j].LEVEL;
		subList.push(list[iOb.j]);
	}

	if ( level != se.LEVEL ) {
		this.do_debug_alert('Error _operator_if: '+ se.TEXT );
		return '';
	}

	var subListIF = new Array();
	var subListCondition = new Array();
	var ifLevel = se.LEVEL + 1;
	var sw = 0;

	subListIF[0] = new Array();
	subListCondition[0] = se;

	for ( var k = 0; k < ( subList.length - 1 ); k++ ) {
		if ( ifLevel == subList[k].LEVEL && ( 'ELSE' == subList[k].EXE || 'ELSIF' == subList[k].EXE ) ) {
			/* Check valid settings ELSE after ELSIF */
			if( 'ELSE' == subListCondition[sw] ) {
				this.do_debug_alert('Error include ELSE before '+ subList[k].EXE);
				return '';
			}
			sw++;
			subListIF[sw] = new Array();
			subListCondition[sw] = subList[k];
			continue;
		}
		subListIF[sw].push(subList[k]);
	}

	/* Go all subListIF */
	for ( var k = 0; k < subListCondition.length; k++ ) {
		if ( 0 == subListIF[k].length ) continue;
		if ( 'IF' == subListCondition[k].EXE || 'UNLESS' == subListCondition[k].EXE || 'ELSIF' == subListCondition[k].EXE ) {
			var condition_line = this._get_condition_line( subListCondition[k].TEXT, subListCondition[k].EXE );
			if ( 'ELSIF' == subListCondition[k].EXE ) fun += ' else  if('+ condition_line +'){';
			else fun += ' if('+ condition_line +'){';
			if ( subListIF[k].length > 0 ) fun += this._exe_list_to_fun_simple( subListIF[k], false ) ;
			fun += "}";
		} else {
			if ( subListIF[k].length > 0 ) fun += " else{"+ this._exe_list_to_fun_simple( subListIF[k], false ) +"}";;
		}
	}

	return fun;
};

/**********************************************************
 *
 *
 *
 *
 * Check and process template function...
 *
 *
 *
 *
 *
**********************************************************/

jtmpl.prototype._comment_cleaner = function( L ) {
	if (!L) return "";
	L = String(L);
	if( -1 == L.indexOf('<!--') ) return L;
	return L.substring( (L.indexOf('<!--') + 4), L.lastIndexOf('-->'));
};

jtmpl.prototype.comment_cleaner_by_id = function( id ) {

	id = this._chop( id, ["'", '"'] );
	if ( String(id).substr(0, 1) == '@' ) {
		this.elems_html[id] = this.GET_CONTENT(String(id).substr(1));
	} else {
		this.elems_html[id] = this._comment_cleaner( this.GET_CONTENT_TO_LINE( id ) );
	}

	return this.elems_html[id];
};

jtmpl.prototype.GET_CONTENT_TO_LINE = function( id ) {
	if ( !id || id == null ) {
		this.do_debug_alert( 'No found element: *** id is empty ***');
		return '';
	}

	if ( this.elems_html[id] && this.elems_html[id] != null )
		return this.elems_html[id];

	var el = this._get_element(id);
	if ( !el || el == null ) {
		this.do_debug_alert( 'No found element: ***'+ id +'***');
		return '';
	}

	return el.innerHTML;
};

/**
 *
 *
 *
 *
 * Check and process variables function...
 *
 *
 *
 *
 *
**/

jtmpl.prototype._create_variable = function( variable ) {
	if ( !variable || variable == '' ) return "(null);";
	variable = String( variable ).replace(this.re_quot_out, '');

	if ( variable.indexOf('.') == -1 ) {
		return " data=(function(d,r){d['"+ variable +"']=r;return d;})(data,to);";
	} else {
		var t = String('"+ variable +"').split('.');
		var L  = "";
		var obj  = "d";
		var lastT = length.pop();
		for ( var i = 1; i < t.length; i++ ) {
			obj  += "["+ t[i] +"]";
			L  += "	if (!"+ obj +") "+ obj +" = {};";
		}
		L  += " data=(function(d,r){ "+ obj +"['"+ lastT +"']=r;return d;})(data,to);";
		return L;
	}
};

/* Parse line to execution javascript line... */
jtmpl.prototype._variable_parse = function ( text, default_undef ) {
	text = this._trim(text);	
	if ( !text || text == 'null' ) return default_undef; 
	if ( text == '""' ) return '""';

	var out = [];
	var FILTER = [];
	var main = this._variable_to_array( text );

	var sL = main.length;
	/* Check FILTER */
	if  ( sL > 0 && main[sL - 1].TYPE == 'NO_QUOTE' ) {
		var t = this._filter_to_array( main[sL - 1].TEXT );
		if ( t.VAR ) main[sL - 1].TEXT = t.VAR;
		else main.pop();
		FILTER = t.FILTER;
	}

	for (var i = 0; i < main.length; i++) {
		if ( !main[i] || !main[i].TEXT ) continue;

		/* parse quotes line */
		if  ( main[i].TYPE == 'QUOTE' ) {
			out.push( this._get_include_dollar_var( main[i].TEXT, default_undef ) );
			continue;
		}

		var varials = main[i].TEXT.match( this.re_CONDITION_MATCH );
		for (var j = 0; j < varials.length; j++ ) {
			if ( varials[j].search( this.re_VAR_SHOT ) == -1 ) {
				out.push( varials[j]  );
				continue;
			}
			varials[j] = this._get_variable_shot( varials[j], default_undef );
			out.push( varials[j] );
		}

	}

	var ounMain = out.join('');
	for (var k = 0; k < FILTER.length; k++) {
		if (!FILTER[k]) continue;
		if ( FILTER[k].search( this.re_VAR_SHOT ) == -1 ) continue;
		ounMain = "obj.filter('"+ FILTER[k] +"',"+ ounMain + ")";
	}

	return ounMain;
};

jtmpl.prototype._variable_to_array = function ( tmpl_line ) {
	var i = 0;
	var main = [];
	var sL = tmpl_line.length;
	var prev = 0;
	var p1 = tmpl_line.indexOf('"');
	var p2 = tmpl_line.indexOf('"', ( p1 + 1 ));

	if( p1 == -1 || p2 == -1 )
		return [ {  'TYPE': 'NO_QUOTE', 'TEXT': this._trim(tmpl_line) } ];

	while ( p1 > -1 && p2 > -1 ) {
		if( prev < p1 ) {
			var t = this._trim(tmpl_line.substring( prev, p1 ));
			if ( t.length > 0 ) 
				main.push({ 'TYPE': 'NO_QUOTE', 'TEXT': t });
		}

		if( (p1 + 1) < p2 ) {		
			var t = this._trim(tmpl_line.substring( (p1 + 1), p2 ));
			if ( t.length > 0 )
				main.push({ 'TYPE': 'QUOTE', 'TEXT': t });
		}


		if ( p2 < ( sL - 2 ) ) {
			var t = this._trim(tmpl_line.substring( p2 + 1 ));
			if ( t.length > 0 )
				main.push({ 'TYPE': 'NO_QUOTE', 'TEXT': t });
		}

		prev = p2 + 1;
		p1 = tmpl_line.indexOf('"', prev);
		p2 = tmpl_line.indexOf('"', p1);
	}

	return main;
};

jtmpl.prototype._filter_to_array = function ( tmpl_line ) {
	var i = 0;
	var main = [];
	
	var sL = tmpl_line.lastIndexOf('||');
	var p1 = tmpl_line.lastIndexOf('|');

	if( p1 == -1 || p1 < sL )
		return { FILTER:[], VAR: this._trim(tmpl_line) };

	p1 = tmpl_line.indexOf('|', sL );

	var no_check_line = null;
	if ( 0 < ( p1 - 1 ) )
		no_check_line = this._trim( tmpl_line.substring( 0, p1 - 1 ) );
	var check_line = this._trim( tmpl_line.substring( p1 + 1 ) );
	var work = check_line.split('|');

	for ( var i = 0; i < work.length; i++ ) {
		if (!work[i] || work[i] == null || work[i].length == 0 ) continue;
		main.push( this._trim( work[i] ));
	}
	return { FILTER: main, VAR: no_check_line };
};


/* Parse variable into "anonym" function  */
jtmpl.prototype._get_variable_shot = function( variable, default_undef ) {
	var nuller = '';

	if (default_undef) nuller = default_undef;
	if (( !variable || variable == '' ) && variable != '0' ) return nuller;

	variable = this._trim(variable);
	if (( !variable || variable == '' ) && variable != '0' ) return nuller;

	/* check ceil number */
	if ( variable == 'false' || variable == 'true' || variable.search(this.re_number) == 0 ) return variable;

	/* check single string */
	if  ( variable.indexOf('"') == 0 && ( variable.lastIndexOf('"') + 1 ) == variable.length ) return '\"'+ variable +'\"';

	/* Check a functions.... no avalible in this time */
	if (  ( variable.lastIndexOf('()') + 2 ) == variable.length  ) {
/* TODO: make it :)) */
	}
	var d = "d."+ variable;
	if ( variable == 'loop' || variable.indexOf('loop.') == 0 ) d = variable;
	return "(function(d,loop){try{if("+ d +")return("+ d +")}catch(e){}return("+ nuller +")})( data, loop )";
};

jtmpl.prototype._get_condition_line = function ( text, type ) {
	var varials = new Array();
	if ( type && 'UNLESS' == type ) { varials.push('!'); varials.push('('); }
	var work = text.match(this.re_CONDITION_MATCH);
	for (var k = 0; k < work.length; k++ ) {
		if ( work[k].search(this.re_CONDITION_SEARCH) > -1 ) {
			varials.push(  work[k] );
			continue;
		}
		if ( '!' == work[k].substring( 0, 1 ) ) {
			varials.push('!');
			work[k] = work[k].substring( 1 );
		}
		varials.push( '(' );
		varials.push( this._variable_parse( work[k], 'false' ) );
		varials.push( ')' );
	}

	if ( type && 'UNLESS' == type ) varials.push(')');
	return varials.join('');
};

jtmpl.prototype._get_include_dollar_var = function ( text, default_undef_in ) {
	text = this._chop( text, ["'", '"'] );

	var i = prev = 0;
	var main = [];

	var p1 = text.indexOf('${', 0);
	if ( p1 == -1 ) return '\"'+ text +'\"';

	var p2 = text.indexOf('}', p1);
	if ( p2 == -1 ) return '\"'+ text +'\"';

	var sL = text.length - 1;

	while ( p1 > -1 && p2 > -1 ) {
		main[i] = '\"'+ text.substring( prev, p1 ) +'\"';

		i++;
		main[i] = this._variable_parse( text.substring( (p1 + 2), p2 ), default_undef_in );

		i++;
		if ( p2 < sL ) main[i] = '\"'+ text.substr( p2 + 1 ) +'\"';

		prev = p2 + 1;
		p1 = text.indexOf('${', prev);
		p2 = text.indexOf('}', p1);
	}

	text = main.join(' + ');
	return text;
};

/**
 *
 *
 *
 *
 * Utils....
 *
 *
 *
 *
**/

jtmpl.prototype._chop = function ( text, what ) {

	if ( !what || typeof what != 'object' || !(what instanceof Array) || what.length == 0 ) what = [ what ];

	if ( !text ) 
		return text;

	var len = text.length - 1;
	for (var i = 0; i < what.length; i++ )
		if ( String(text).indexOf(what[i]) == 0 && String(text).lastIndexOf(what[i]) == len )
			return text.substring( 1, len );

	return text;
};

/* Change start and finish tags into template */
jtmpl.prototype._clone = function( data ) {
	if ( data == undefined || !data ) return data;
	if ( typeof data != 'object' ) return data;
	var out = null;
	if ( data instanceof Array ) {
		var out = new Array();
		for ( var i = 0; i < data.length; i++) out[i] = this._clone(data[i]);
	} else if ( data instanceof Object ) {
		var out = new Object();
		for (var i in data) out[i] = this._clone(data[i]);
	}

	return out;
};


jtmpl.prototype._get_element = function ( el ) {
	if ( typeof el != 'object' ) el = document.getElementById( el );
	if ( typeof el == 'object' ) return el;
};

jtmpl.prototype._get_loop = function( list, i ) {

	var loop = { size:-1, max: -1, index: -1, count: -1, first: false, last: false, next: null, prev: null };
	loop.size = list.length;
	loop.max = list.length - 1;
	loop.index = String(i);
	loop.count = i+1;

	if ( i == 0 ) loop.first = true;
	if ( i == ( list.length - 1 ) ) loop.last = true;
	if ( i < ( list.length - 1 ) ) loop.next = list[i+1];
	if ( i > 0 ) loop.prev = list[i-1];

	return loop;
};

jtmpl.prototype._get_loop_data = function( data, param, list, i ) {
	var d1 = data;
	d1[param] = list[i];
	d1['loop']=this._get_loop(list,i);
	return d1;
};

jtmpl.prototype._get_loop_data_shot = function( data, param, list, i ) {
	data[param] = list[i];
	var loop = this._get_loop( list, i );
	return loop;
};

jtmpl.prototype._check_loop = function( list ) {
	if ( list && typeof list == 'object' && list instanceof Array && list.length > 0 ) return true;
	return false;
};

jtmpl.prototype._trim = function( text ) {
	return String(text).replace( this.re_e_space, '').replace( this.re_s_space, '');
};

//jtmpl.prototype.GET_CONTENT = function (u) { jtmpl.prototype.GET_CONTENT_TO_LINE(u); };

})();